<template>
  <el-container style="height: 100%">
    <el-aside style="border:0.5px solid #DCDCDC;width: 11%;height: 100%">
      <div><h5>工作区</h5></div>
      <div style="margin-left:10px;margin-right:10px;border: 1px solid #DCDCDC;height: 160px">
        <el-select v-model="selectedWorkspace" placeholder="选择工作区" size="small"
                   style="width: 145px;margin:10px">
          <el-option
              v-for="workspace in workspacesData"
              :key="workspace.id"
              :label="workspace.name"
              :value="workspace.id"
              @click=onWorkspaceChanged(workspace)
          />
        </el-select>
        <el-menu class="el-menu-vertical-demo">
          <el-menu-item index="1" @click="selectFolder">
            <el-icon>
              <FolderOpened/>
            </el-icon>
            <span>创建工作区</span>
          </el-menu-item>
          <el-menu-item index="2">
            <el-icon>
              <FolderChecked/>
            </el-icon>
            <span>保存工作区</span>
          </el-menu-item>
        </el-menu>
      </div>
      <div><h5>手动标注</h5></div>
      <div style="margin-left:10px;margin-right:10px;border: 1px solid #DCDCDC;height: 115px">
        <el-menu class="el-menu-vertical-demo">
          <el-menu-item index="1" @click="drawShape('rectangle')">
            <el-icon>
              <FullScreen/>
            </el-icon>
            <span>创建长方形</span>
          </el-menu-item>
          <el-menu-item index="2" @click="drawShape('polygon')">
            <el-icon>
              <Share/>
            </el-icon>
            <span>创建多边形</span>
          </el-menu-item>
        </el-menu>
      </div>
      <div><h5>自动标注</h5></div>
      <div style="margin-left:10px;margin-right:10px;border: 1px solid #DCDCDC;height: 50px">
        <el-checkbox v-model="smartAnnoYN" label="开启自动标注" size="small" style="width: 145px;margin:10px"
                     @change="onSmartAnnoChanged"/>
        <!--        <el-select v-model="selectedModel" placeholder="模型选择" size="small"-->
        <!--                   style="width: 145px;margin:10px">-->
        <!--          <el-option-->
        <!--              v-for="model in models"-->
        <!--              :key="model.id"-->
        <!--              :label="model.name"-->
        <!--              :value="model.id"-->
        <!--              @click=onModelChanged(model)-->
        <!--          />-->
        <!--        </el-select>-->
      </div>
      <div><h5>数据列表</h5></div>
      <div style="margin-left:10px;margin-right:10px;border: 1px solid #DCDCDC;height: 250px">
        <el-table :scrollbar-always-on="on"
                  :data="filesData"
                  @row-click="selectImage"
                  size="small">
          <el-table-column :header-align="'center'" prop="name" label="文件名" sortable/>
        </el-table>
      </div>
    </el-aside>
    <el-main style="margin-left:10px;width: 70%;border:0.5px solid #DCDCDC">
      <div id="konvacanvas" style="width: 100%;height: 100%">
        <v-stage
            ref="stageRef"
            :config="stageConfig"
            @mousedown="handleMouseDown"
            @mousemove="handleMouseMove"
            @mouseup="handleMouseUp"
            @dblclick="handleMouseDBClick"
        >
          <v-layer ref="layer">
            <v-image :config="imageConfig"/>
            <template v-for="(instance,index) in allLabelInstances" :key="index">
              <v-rect v-if="instance.type=='rectangle'"
                      :config="instance"
                      @dragmove="handleDragMove"
                      @dragend="handleDragEnd"
              />
              <v-line v-if="instance.type=='polygon'"
                      :config="instance"
                      @dragmove="handleDragMove"
                      @dragend="handleDragEnd"
              />
            </template>
            <v-rect v-if="currentLabelInstance&&drawingMode.mode=='rectangle'" :config="currentLabelInstance"/>
            <v-line v-if="currentLabelInstance&&drawingMode.mode=='polygon'" :config="currentLabelInstance"/>
            <template v-for="(point,index) in smartAnnoPoints.points" :key="index">
              <v-circle :config="{
                x:point.x,
                y:point.y,
                radius:5,
                fill: '#fc0303',
                shadowColor: '#FC0303FF',
                shadowBlur: 20,
                shadowOpacity: 1
              }"/>
            </template>
          </v-layer>
        </v-stage>
      </div>
    </el-main>
    <el-aside style="margin-left:10px;border:1px solid #DCDCDC;width: 11%;height: 100%">
      <div><h5>标签列表</h5></div>
      <div style="margin-left:10px;margin-right:10px;border: 1px solid #DCDCDC;height: 200px;overflow: auto">
        <div style="display: flex;padding-left: 10px;padding-top:5px">
          <el-button link type="primary" style="font-size: small" @click="addLabel">新增</el-button>
          <el-button link type="primary" style="font-size: small" @click="deleteLabels">删除</el-button>
        </div>
        <div>
          <div style="display: flex;align-items:center;gap: 5px;padding-left: 5px;padding-right: 5px"
               v-for="(label,index) in labelList" :key="label.id">
            <el-checkbox @change="(value)=>selectLabel(index,value)"/>
            <el-input v-model="label.name" style="height: 25px" v-if="label.editStatus==0"/>
            <span v-if="label.editStatus==1">{{ label.name }}</span>
            <el-color-picker v-model="label.color" :size="'small'" v-if="label.editStatus==1" disabled/>
            <el-color-picker v-model="label.color" :size="'small'" v-if="label.editStatus==0"/>
            <el-button link type="primary" style="font-size: small" v-if="label.editStatus==0"
                       @click="saveLabel(index)">保存
            </el-button>
            <el-button link type="primary" style="font-size: small" v-if="label.editStatus==1"
                       @click="editLabel(index)">编辑
            </el-button>
          </div>
        </div>
      </div>
      <div><h5>标签实例</h5></div>
      <div style="margin-left:10px;margin-right:10px;border: 1px solid #DCDCDC;height: 200px;overflow: auto">
        <div style="display: flex;padding-left: 10px;padding-top: 5px">
          <el-button link type="primary" style="font-size: small" @click="deleteLabelInstances()">删除</el-button>
          <el-button link type="primary" style="font-size: small" @click="combineLabelInstances()">合并</el-button>
        </div>
        <div style="display: flex;align-items:center;gap: 5px;padding-left: 5px;padding-right: 5px"
             v-for="(instance,index) in allLabelInstances" :key="instance.id">
          <el-checkbox @change="(value)=>selectLabelInstance(index,value)"/>
          <el-select v-model="instance.label" placeholder="标签选择" :size="'small'" v-if="instance.editStatus==0">
            <el-option
                v-for="label in labelList"
                :key="label.id"
                :label="label.name"
                :value="label.name"
                @click="onLabelChanged(index,label)"
            />
          </el-select>
          <span v-if="instance.editStatus==1">{{ instance.label }}</span>
          <el-color-picker v-model="instance.color" :size="'small'" disabled/>
          <el-button link type="primary" style="font-size: small" v-if="instance.editStatus==0"
                     @click="saveLabelInstance(index)">保存
          </el-button>
          <el-button link type="primary" style="font-size: small" v-if="instance.editStatus==1"
                     @click="editLabelInstance(index)">编辑
          </el-button>
        </div>
      </div>
      <div><h5>标签文件</h5></div>
      <div style="margin-left:10px;margin-right:10px;border: 0.5px solid #DCDCDC;height: 230px;overflow: auto">
        <div style="display: flex;padding-left: 10px;padding-top: 5px">
          <el-button link type="primary" style="font-size: small" @click="generateLabelFile()">生成当前标签文件
          </el-button>
        </div>
        <el-input size="small" v-model="findStr" style="width: 145px;margin:10px" placeholder="查询文件"/>
        <el-table
            :data="labelFiles"
            :scrollbar-always-on="on"
            size="small">
          <el-table-column :header-align="'center'" prop="name" label="文件名" sortable/>
        </el-table>
      </div>
    </el-aside>
    <el-dialog v-model="createWorkSpaceDialogVisible" style="width: 400px;height: 220px">
      <div style="text-align: left">
        <h4>创建工作区</h4>
      </div>
      <div style="display: inline-flex;width: 100%">
        <div style="width: 100px">工作区名称:</div>
        <el-input v-model="workspaceName" placeholder="" size="small"/>
      </div>
      <!--      <div style="display: inline-flex;padding-top:10px;width: 100%">-->
      <!--        <div style="width: 100px">工作区路径:</div>-->
      <!--        <el-input v-model="workspaceFolder" placeholder=""/>-->
      <!--      </div>-->
      <div style="padding-top: 10px;text-align: left">
        <el-button link type="primary" @click="submitSelectedFolder">确定</el-button>
        <el-button link type="primary" @click="cancelSelectFolder">取消</el-button>
      </div>
    </el-dialog>
  </el-container>
</template>
<script>
import config from '@/assets/config'
import {ref} from 'vue'
import {ElMessage} from 'element-plus'

export default {
  name: 'AnnoView',
  setup: function () {

    const domain = ref("http://" + config.server.ip + ":" + config.server.port)
    const models = ref([
      {"id": "", "name": "", "type": ""}
    ])
    const selectedModel = ref("")
    const createWorkSpaceDialogVisible = ref(false)
    const workspacesData = ref([
      {"id": "", "name": "", "path": ""}
    ])
    const selectedWorkspace = ref("")
    const workspaceName = ref("")
    const labelList = ref([])
    const selectedLabels = ref(new Set())
    const filesData = ref([])
    const labelFiles = ref([])
    const findStr = ref("")
    const currentImage = ref("")
    const stageRef = ref(null)
    const stageConfig = ref({width: window.innerWidth, height: window.innerHeight, scaleX: 1, scaleY: 1})
    const imageConfig = ref({x: 0, y: 0, image: null, width: 0, height: 0})
    const imgData = ref(null)
    const imgOriWidth = ref(0)
    const imgOriHeight = ref(0)
    const drawingMode = ref({"drawing": false, "mode": ""})
    const isDrawing = ref(false)
    const currentLabelInstance = ref(null)
    const allLabelInstances = ref([])
    const selectedLabelInstances = ref(new Set())
    const smartAnnoYN = ref(false)
    const smartAnnoPoints = ref({"points": [], "labels": []})
    const promptsData = ref({"points": [], "labels": []})
    const addLabel = () => {
      const label = {"id": "", "name": "", "color": "#ee0c0c", "editStatus": 0};
      labelList.value.push(label)
    }
    const saveLabel = (index) => {
      const savedLabel = labelList.value[index];
      savedLabel["workspaceId"] = selectedWorkspace.value
      fetch(domain.value + "/elearning/saveLabel", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify(savedLabel)
      })
          .then(response => response.json())
          .then(data => {
            if (data.status == 1) {
              labelList.value[index].editStatus = 1
              labelList.value[index].id = data.labelId
            }
          })
    }
    const editLabel = (index) => {
      labelList.value[index].editStatus = 0
    }
    const findLabels = () => {
      if (selectedWorkspace.value != "") {
        fetch(domain.value + "/elearning/findLabels?workspaceId=" + selectedWorkspace.value)
            .then(response => response.json())
            .then(data => {
              labelList.value = data.results
            })
      }
    }
    const selectLabel = (index, value) => {
      const labelId = labelList.value[index].id;
      if (value) {
        selectedLabels.value.add(labelId)
      } else {
        if (selectedLabels.value.has(labelId)) {
          selectedLabels.value.delete(labelId)
        }
      }
    }
    const deleteLabels = () => {
      const ids = Array.from(selectedLabels.value).join(",");
      const data = {"ids": ids};
      fetch(domain.value + "/elearning/deleteLabels", {
        method: "POST",
        headers: {
          "Content-Type": "application/json"
        },
        body: JSON.stringify(data)
      })
          .then(response => response.json())
          .then(data => {
            if (data.status == 1) {
              findLabels()
            }
          })
    }
    const selectFolder = () => {
      createWorkSpaceDialogVisible.value = true
    }
    const cancelSelectFolder = () => {
      createWorkSpaceDialogVisible.value = false
    }
    const submitSelectedFolder = () => {
      if (workspaceName.value == "") {
        ElMessage("工作区名称不能为空！")
        return
      }
      const folder = {"workspaceName": workspaceName.value};
      fetch(domain.value + "/elearning/createWorkspace", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify(folder)
      })
          .then(response => response.json())
          .then(data => {
            if (data.status == 1) {
              ElMessage("工作区创建成功")
              createWorkSpaceDialogVisible.value = false
            } else {
              ElMessage("无法创建工作区！")
            }
          })
    }
    const findModel = () => {
      fetch(domain.value + "/elearning/findModel")
          .then(response => response.json())
          .then(data => {
            if (data.status) {
              models.value = data.results
            } else {
              ElMessage(data.message)
            }

          })
    }
    const onSmartAnnoChanged = (newVal) => {
      if (newVal) {
        findModel()
      } else {
        models.value = []
      }
    }

    const onModelChanged = (model) => {
      selectedModel.value = model.id
    }

    const findAnnoDatas = () => {
      if (selectedWorkspace.value != "") {
        fetch(domain.value + "/elearning/findAnnoDatas?workspaceId=" + selectedWorkspace.value)
            .then(response => response.json())
            .then(data => {
              filesData.value = data.results
              createWorkSpaceDialogVisible.value = false
            })
      }
    }

    const findLabelFiles = () => {
      if (selectedWorkspace.value != "") {
        const formData = {"workspaceid": selectedWorkspace.value, "findStr": findStr.value}
        fetch(domain.value + "/elearning/findLabelFiles", {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
          },
          body: JSON.stringify(formData)
        })
            .then(response => response.json())
            .then(data => {
              labelFiles.value = data.result
            })
      }
    }

    const findWorkspaces = () => {
      fetch(domain.value + "/elearning/findWorkspaces")
          .then(response => response.json())
          .then(data => {
            if (data.status) {
              workspacesData.value = data.results
            } else {
              ElMessage(data.message)
            }

          })
    }


    const onWorkspaceChanged = (workspace) => {
      selectedWorkspace.value = workspace.id
      findLabels()
      findAnnoDatas()
      findLabelFiles()
    }
    const setStage = () => {
      stageConfig.value.width = document.getElementById("konvacanvas").offsetWidth
      stageConfig.value.height = document.getElementById("konvacanvas").offsetHeight
    }
    const selectImage = async (image) => {
      currentImage.value = image.name
      const imgUrl = domain.value + "/elearning/" + selectedWorkspace.value + "/" + image.name;
      const img = new Image()
      img.src = imgUrl
      img.onload = () => {
        imgOriWidth.value = img.width
        imgOriHeight.value = img.height
        imgData.value = img
        updateImageConfig()
      }
      img.onerror = (err) => {
        console.error("图像加载错误：", err)
      }
      findLabelInstances()
    }
    const updateImageConfig = () => {
      const stageW = stageConfig.value.width
      const stageH = stageConfig.value.height
      const canvasRatio = stageW / stageH
      const imageRatio = imgOriWidth.value / imgOriHeight.value
      let newWidth, newHeight, newX, newY
      if (canvasRatio > imageRatio) {
        //画布要限制图像更长的那条边
        //如果画布长宽比更大，则图像的高度要适应画布的高度
        newHeight = stageH
        newWidth = imgOriWidth.value / imgOriHeight.value * stageH
        newX = (stageW - newWidth) / 2
        newY = 0
      } else {
        //如果图像长宽比更大，则图像的宽度要画布的宽度
        newWidth = stageW
        newHeight = imgOriHeight.value / imgOriWidth.value * stageW
        newX = 0
        newY = (stageH - newHeight) / 2
      }
      imageConfig.value = {
        ...imageConfig.value,
        "image": imgData.value,
        x: newX,
        y: newY,
        width: newWidth,
        height: newHeight
      }
    }
    const drawShape = (type) => {
      drawingMode.value.drawing = true
      drawingMode.value.mode = type
    }
    const handleMouseDown = (evt) => {
      if (drawingMode.value.drawing) {
        const stage = evt.target.getStage()
        const pos = stage.getPointerPosition()
        // 不需要考虑处于自动标注的状态下的鼠标事件
        if (!smartAnnoYN.value && checkPointerPos(pos)) {
          if (drawingMode.value.mode == "rectangle") {
            isDrawing.value = true
            currentLabelInstance.value = {
              x: pos.x,
              y: pos.y,
              width: 0,
              height: 0,
            }
          }
          if (drawingMode.value.mode == "polygon") {
            isDrawing.value = true
            if (!currentLabelInstance.value) {
              currentLabelInstance.value = {
                points: [],
                stroke: "#9BFA86FF",
                strokeWidth: 2,
                fill: "#9BFA86FF",
                opacity: 0.6,
                dash: [4, 4],
                editStatus: 0,
                draggable: true,
                closed: true,
                type: drawingMode.value.mode,
                imagex: parseFloat(imageConfig.value.x).toFixed(2),
                imagey: parseFloat(imageConfig.value.y).toFixed(2)
              }
            }
            if (currentLabelInstance.value.points.length == 0) {
              currentLabelInstance.value.points.push(pos.x, pos.y)
            }
            currentLabelInstance.value.newLine = true//点击后开始画新的线
          }
          return;
        }
      }
    }
    const handleMouseMove = (evt) => {
      if (isDrawing.value) {
        const stage = evt.target.getStage()
        const pos = stage.getPointerPosition()
        if (!smartAnnoYN.value) {
          if (drawingMode.value.mode == "rectangle") {
            const clampedX = Math.max(imageConfig.value.x, Math.min(pos.x, imageConfig.value.x + imageConfig.value.width))
            const clampedY = Math.max(imageConfig.value.y, Math.min(pos.y, imageConfig.value.y + imageConfig.value.height))
            const x = Math.min(currentLabelInstance.value.x, clampedX)
            const y = Math.min(currentLabelInstance.value.y, clampedY)
            const width = Math.abs(clampedX - currentLabelInstance.value.x)
            const height = Math.abs(clampedY - currentLabelInstance.value.y)
            currentLabelInstance.value = {
              id: "",
              x: x,
              y: y,
              width: width.toFixed(2),
              height: height.toFixed(2),
              stroke: "#9BFA86FF",
              strokeWidth: 2,
              fill: "#9BFA86FF",
              opacity: 0.6,
              dash: [4, 4],
              label: "",
              color: "#9BFA86FF",
              editStatus: 0,
              draggable: true,
              type: drawingMode.value.mode,
              imagex: parseFloat(imageConfig.value.x).toFixed(2),
              imagey: parseFloat(imageConfig.value.y).toFixed(2),
            }
          }
          if (drawingMode.value.mode == "polygon") {
            if (currentLabelInstance.value.newLine) {
              currentLabelInstance.value.newLine = false
              currentLabelInstance.value.points.push(pos.x, pos.y)
            } else {
              let len = currentLabelInstance.value.points.length
              let points = currentLabelInstance.value.points
              points[len - 2] = pos.x
              points[len - 1] = pos.y
              currentLabelInstance.value = {
                id: "",
                points: points,
                stroke: "#9BFA86FF",
                strokeWidth: 2,
                fill: "#9BFA86FF",
                opacity: 0.6,
                dash: [4, 4],
                editStatus: 0,
                draggable: true,
                closed: true,
                type: drawingMode.value.mode,
                imagex: parseFloat(imageConfig.value.x).toFixed(2),
                imagey: parseFloat(imageConfig.value.y).toFixed(2)
              }
            }
          }
        }
      }
    }
    const handleMouseUp = () => {
      if (!smartAnnoYN.value) {
        if (checkCurrentLabelInstance() && drawingMode.value.mode == "rectangle") {
          allLabelInstances.value.push({
            ...currentLabelInstance.value,
            dash: []
          })
          isDrawing.value = false
          currentLabelInstance.value = null
        }
      }
    }
    const handleMouseDBClick = (evt) => {
      if (smartAnnoYN.value) {
        const stage = evt.target.getStage()
        const pos = stage.getPointerPosition()
        // const pointX = pos.x - imageConfig.value.x //基于图像的坐标x
        // const pointY = pos.y - imageConfig.value.y //基于图像的坐标y
        const point = {x: pos.x, y: pos.y}
        const label = [1]
        smartAnnoPoints.value.points.push(point)
        smartAnnoPoints.value.labels.push(label)
        const relatedPointX = pos.x - imageConfig.value.x
        const relatedPointY = pos.y - imageConfig.value.y
        const promptPoint = {x: relatedPointX, y: relatedPointY}
        const promptLabel = [1]
        promptsData.value.points.push(promptPoint)
        promptsData.value.labels.push(promptLabel)
        promptsData.value["workspaceId"] = selectedWorkspace.value
        promptsData.value["imageName"] = currentImage.value
        promptsData.value["frontImageWidth"] = imageConfig.value.width
        promptsData.value["frontImageHeight"] = imageConfig.value.height
        promptsData.value["imageConfigX"] = imageConfig.value.x
        promptsData.value["imageConfigY"] = imageConfig.value.y
        submitPromptData(promptsData.value)

      } else {
        if (checkCurrentLabelInstance() && drawingMode.value.mode == "polygon") {
          allLabelInstances.value.push({
            ...currentLabelInstance.value,
            dash: []
          })
          isDrawing.value = false
          currentLabelInstance.value = null
        }
      }

    }
    // 判断绘制图形的宽度和高度的尺寸是否大于5，是，则符合绘制要求
    const checkCurrentLabelInstance = () => {
      let checked = false
      if (isDrawing.value && currentLabelInstance.value && drawingMode.value.mode == "rectangle"
          && currentLabelInstance.value.width > 5
          && currentLabelInstance.value.height > 5) {
        checked = true
      }
      if (isDrawing.value && currentLabelInstance.value && drawingMode.value.mode == "polygon") {
        let points = currentLabelInstance.value.points
        let x = []
        let y = []
        for (let i = 0; i < points.length; i = i + 2) {
          x.push(points[i])
          y.push(points[i + 1])
        }
        let xDiff = Math.max(...x) - Math.min(...x)
        let yDiff = Math.max(...y) - Math.min(...y)
        if (xDiff > 5 && yDiff > 5) {
          checked = true
        }
      }
      return checked
    }
    const checkPointerPos = (pos) => {
      if (pos.x >= imageConfig.value.x
          && pos.x <= (imageConfig.value.x + imageConfig.value.width)
          && pos.y >= imageConfig.value.y
          && pos.y <= (imageConfig.value.y + imageConfig.value.height)) {
        return true
      } else {
        return false
      }
    }
    //鼠标滚轮操作，以鼠标所在位置为中心缩放
    const handleWheel = (e) => {
      e.evt.preventDefault()
      const stage = stageRef.value.getStage()
      const oldScale = stage.scaleX
      const scaleBy = 1.1
      const pointer = stage.getPointerPosition()
      const direction = e.evt.deltaY > 0 ? 1 / scaleBy : scaleBy
      const newScale = oldScale * direction
      const mousePointTo = {
        x: (pointer.x - stage.x()) / oldScale,
        y: (pointer.y - stage.y()) / oldScale
      };

      const newPos = {
        x: pointer.x - mousePointTo.x * newScale,
        y: pointer.y - mousePointTo.y * newScale
      };

      stageConfig.value.scaleX = newScale;
      stageConfig.value.scaleY = newScale;
      stageConfig.value.x = newPos.x;
      stageConfig.value.y = newPos.y;

      stage.position(newPos);
      stage.scale({x: newScale, y: newScale});
      stage.batchDraw();
    }
    const handleKeyDown = (evt) => {
      if (drawingMode.value.drawing && evt.key == "Escape") {
        drawingMode.value.drawing = false
        drawingMode.value.mode = ""
        ElMessage("已退出绘制模式")
      } else {
        return
      }
    }
    const addEvents = () => {
      window.addEventListener("keydown", handleKeyDown)
    }
    const onLabelChanged = (index, label) => {
      allLabelInstances.value[index].label = label.name
      allLabelInstances.value[index].fill = label.color
      allLabelInstances.value[index].color = label.color
      allLabelInstances.value[index].stroke = label.color
    }
    const saveLabelInstance = (index) => {
      const savedLabelInstance = allLabelInstances.value[index];
      savedLabelInstance["workspaceId"] = selectedWorkspace.value
      savedLabelInstance["filename"] = currentImage.value
      fetch(domain.value + "/elearning/saveLabelInstance", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify(savedLabelInstance)
      })
          .then(response => response.json())
          .then(data => {
            if (data.status == 1) {
              allLabelInstances.value[index].editStatus = 1
              allLabelInstances.value[index].id = data.instanceId
            }
          })
    }
    const findLabelInstances = () => {
      if (selectedWorkspace.value != "" && currentImage.value != "") {
        fetch(domain.value + "/elearning/findLabelInstances?workspaceId=" + selectedWorkspace.value + "&filename=" + currentImage.value)
            .then(response => response.json())
            .then(data => {
              allLabelInstances.value = data.results
            })
      }
    }
    const editLabelInstance = (index) => {
      allLabelInstances.value[index].editStatus = 0
    }
    const selectLabelInstance = (index, value) => {
      const instanceId = allLabelInstances.value[index].id;
      if (value) {
        selectedLabelInstances.value.add(instanceId)
      } else {
        selectedLabelInstances.value.delete(instanceId)
      }
    }
    const deleteLabelInstances = () => {
      const ids = Array.from(selectedLabelInstances.value).filter(item => {
        return item != null && item.toString().trim() != ""
      }).join(",");
      const data = {"ids": ids};
      fetch(domain.value + "/elearning/deleteLabelInstances", {
        method: "POST",
        headers: {
          "Content-Type": "application/json"
        },
        body: JSON.stringify(data)
      })
          .then(response => response.json())
          .then(data => {
            if (data.status == 1) {
              findLabelInstances()
            }
          })
    }

    const combineLabelInstances = () => {
      const ids = Array.from(selectedLabelInstances.value).filter(item => {
        return item != null && item.toString().trim() != ""
      }).join(",");
      const data = {"ids": ids}
      fetch(domain.value + "/elearning/combineLabelInstances", {
        method: "POST",
        headers: {
          "Content-Type": "application/json"
        },
        body: JSON.stringify(data)
      })
          .then(response => response.json())
          .then(data => {
            if (data.status == 1) {
              findLabelInstances()
            } else {
              ElMessage(data.message)
            }
          })
    }
    const generateLabelFile = () => {
      const formData = {
        "workspaceid": selectedWorkspace.value,
        "filename": currentImage.value,
        "imageConfigWidth": imageConfig.value.width,
        "imageConfigHeight": imageConfig.value.height
      }
      fetch(domain.value + "/elearning/generateLabelFile", {
        method: "POST",
        headers: {
          "Content-Type": "application/json"
        },
        body: JSON.stringify(formData)
      })
          .then(response => response.json())
          .then(data => {
            if (data.status == 1) {
              findLabelFiles()
            }
            ElMessage(data.message)
          })
    }

    const submitPromptData = (prompts) => {
      fetch(domain.value + "/elearning/samPredict", {
        method: "POST",
        headers: {
          "Content-Type": "application/json"
        },
        body: JSON.stringify(prompts)
      })
          .then(response => response.json())
          .then(data => {
            let smartLabelInstance = {
              id: "",
              points: data["result"],
              stroke: "#9BFA86FF",
              strokeWidth: 2,
              fill: "#9BFA86FF",
              opacity: 0.6,
              dash: [4, 4],
              editStatus: 0,
              draggable: true,
              closed: true,
              type: "polygon",
              imagex: parseFloat(imageConfig.value.x).toFixed(2),
              imagey: parseFloat(imageConfig.value.y).toFixed(2)
            }
            allLabelInstances.value.push({
              ...smartLabelInstance,
              dash: []
            })
            promptsData.value = {"points": [], "labels": []}
            smartAnnoPoints.value.points.pop()

          })
    }

    const handleDragMove = (e) => {
      isDrawing.value = false
      if (e.target.attrs.type == "rectangle") {
        let xAllowedMoveMax = imageConfig.value.x + imageConfig.value.width - e.target.attrs.width - 1
        let xAllowedMoveMin = imageConfig.value.x + 1
        let yAllowedMoveMax = imageConfig.value.y + imageConfig.value.height - e.target.attrs.height - 1
        let yAllowedMoveMin = imageConfig.value.y + 1
        if (e.target.x() > xAllowedMoveMax) {
          e.target.x(Math.min(e.target.x(), xAllowedMoveMax))
        } else {
          e.target.x(Math.max(e.target.x(), xAllowedMoveMin))
        }
        if (e.target.y() > yAllowedMoveMax) {
          e.target.y(Math.min(e.target.y(), yAllowedMoveMax))
        } else {
          e.target.y(Math.max(e.target.y(), yAllowedMoveMin))
        }
      }
      if (e.target.attrs.type == "polygon") {
        const shape = e.target
        const box = shape.getClientRect()
        const pos = shape.position()
        let xAllowedMoveMax = imageConfig.value.x + imageConfig.value.width - box.width - 1
        let xAllowedMoveMin = imageConfig.value.x + 1
        let yAllowedMoveMax = imageConfig.value.y + imageConfig.value.height - box.height - 1
        let yAllowedMoveMin = imageConfig.value.y + 1
        let dx = 0, dy = 0
        if (box.x < xAllowedMoveMin) {
          dx = xAllowedMoveMin - box.x
        }
        if (box.x > xAllowedMoveMax) {
          dx = xAllowedMoveMax - box.x
        }
        if (box.y < yAllowedMoveMin) {
          dy = yAllowedMoveMin - box.y
        }
        if (box.y > yAllowedMoveMax) {
          dy = yAllowedMoveMax - box.y
        }
        if (dx != 0 || dy != 0) {
          shape.x(pos.x + dx)
          shape.y(pos.y + dy)
        } else {
          shape.x(pos.x)
          shape.y(pos.y)
        }
      }
    }
    const handleDragEnd = (e) => {
      allLabelInstances.value[e.target.index - 1].x = e.target.attrs.x
      allLabelInstances.value[e.target.index - 1].y = e.target.attrs.y
      saveLabelInstance(e.target.index - 1)
    }
    return {
      domain,
      models,
      selectedModel,
      selectedWorkspace,
      createWorkSpaceDialogVisible,
      workspacesData,
      workspaceName,
      labelList,
      selectedLabels,
      filesData,
      labelFiles,
      findStr,
      stageRef,
      stageConfig,
      imageConfig,
      drawingMode,
      currentLabelInstance,
      allLabelInstances,
      selectedLabelInstances,
      smartAnnoYN,
      smartAnnoPoints,
      promptsData,
      addLabel,
      saveLabel,
      editLabel,
      findLabels,
      selectLabel,
      deleteLabels,
      selectFolder,
      cancelSelectFolder,
      submitSelectedFolder,
      findModel,
      onModelChanged,
      onSmartAnnoChanged,
      findAnnoDatas,
      findLabelFiles,
      findWorkspaces,
      onWorkspaceChanged,
      setStage,
      selectImage,
      updateImageConfig,
      drawShape,
      handleMouseDown,
      handleMouseMove,
      handleMouseUp,
      handleMouseDBClick,
      handleWheel,
      handleKeyDown,
      addEvents,
      checkPointerPos,
      onLabelChanged,
      saveLabelInstance,
      findLabelInstances,
      submitPromptData,
      editLabelInstance,
      selectLabelInstance,
      deleteLabelInstances,
      combineLabelInstances,
      generateLabelFile,
      handleDragMove,
      handleDragEnd,
      checkCurrentLabelInstance,
    }
  },
  mounted() {
    this.setStage()
    this.addEvents()
  },
  created() {
    this.findWorkspaces()
  }
}
</script>
